﻿using System;
using System.Collections.Generic;

using System.Text;

namespace System.Qizx.Xml
{
    /*******************************/
    /// <summary>
    /// Supports the XSL transformations.
    /// </summary>
    public class TransformerSupport
    {
        private System.Xml.Xsl.XsltArgumentList Parameters = null;
        private TransformerResolver resolverFactory = null;
        private TransformerResolver resolverTransformer = null;

        private System.Xml.XmlResolver DefaultResolverFactory = null;
        private System.Xml.XmlResolver DefaultResolverTransformer = null;

        private XsltExceptionManager errorListenerFactory = null;
        private XsltExceptionManager errorListenerTransformer = null;
        private System.Xml.Xsl.XslTransform Transformer = null;
        private BasicSource Stylesheet = null;

        /// <summary>
        /// The constructor of the support class.
        /// </summary>
        public TransformerSupport()
        {
            this.Transformer = new System.Xml.Xsl.XslTransform();
            this.errorListenerFactory = new DefaultXsltExceptionManager();
            this.errorListenerTransformer = new DefaultXsltExceptionManager();
            this.ResolverFactory = null;
        }

        /// <summary>
        /// A static constructor for this class.
        /// </summary>
        /// <returns>A new instance of tranformer support.</returns>
        public static TransformerSupport NewInstance()
        {
            return new TransformerSupport();
        }

        /// <summary>
        /// Creates a new instance of TransformerSupport and sets it ResolverFactory and errorListenerFactory.
        /// </summary>
        /// <param name="transformer">Instance of TransformerSupport to get its attributes to create the new 
        /// instance.</param>
        /// <returns>The new instance.</returns>
        public static TransformerSupport NewTransform(TransformerSupport transformer)
        {
            TransformerSupport temp = new TransformerSupport();
            temp.ResolverFactory = transformer.ResolverFactory;
            temp.errorListenerFactory = transformer.errorListenerFactory;
            return temp;
        }

        /// <summary>
        /// Clears the parameters asociated with the XslTransform instance.
        /// </summary>
        public void ClearArguments()
        {
            Parameters.Clear();
            Parameters = null;
        }

        /// <summary>
        /// Gets and sets the class that manages the errors reported by the XslTransform.
        /// </summary>
        public XsltExceptionManager ErrorListenerFactory
        {
            get
            {
                return this.errorListenerFactory;
            }
            set
            {
                if (value != null)
                    this.errorListenerFactory = value;
                else
                    throw new System.ArgumentException("Error assigning the error listener: a null ErrorListener was received");
            }
        }

        /// <summary>
        /// Gets and sets the class that manages the errors reported by the XslTransform.
        /// </summary>
        public XsltExceptionManager ErrorListenerTransformer
        {
            get
            {
                return this.errorListenerTransformer;
            }
            set
            {
                if (value != null)
                    this.errorListenerTransformer = value;
                else
                    throw new System.ArgumentException("Error assigning the error listener: a null ErrorListener was received");
            }
        }

        /// <summary>
        /// Gets and sets the class that is used to resolve externs references.
        /// </summary>
        public TransformerResolver ResolverTransformer
        {
            get
            {
                return this.resolverTransformer;
            }
            set
            {
                this.resolverTransformer = value;
                this.DefaultResolverTransformer = new DefaultTransformerResolver();
                ((DefaultTransformerResolver)DefaultResolverTransformer).UriResolver = this.resolverTransformer;
            }
        }

        /// <summary>
        /// Gets and sets the class that is used to resolve externs references in load methods.
        /// </summary>
        public TransformerResolver ResolverFactory
        {
            get
            {
                return this.resolverFactory;
            }
            set
            {
                this.resolverFactory = value;
                this.DefaultResolverFactory = new DefaultTransformerResolver();
                ((DefaultTransformerResolver)DefaultResolverFactory).UriResolver = this.resolverFactory;
                if (this.ResolverTransformer == null)
                    this.ResolverTransformer = value;
            }
        }

        /// <summary>
        /// Loads the StyleSheet that will be used for the transformations operations.
        /// </summary>
        /// <param name="StyleSheet">A XPathDocument that contains the StyleSheet.</param>
        public void Load(System.Xml.XPath.XPathDocument StyleSheet)
        {
            try
            {
                Transformer.Load(StyleSheet, DefaultResolverFactory, this.GetType().Assembly.Evidence);
                this.Stylesheet = new GenericSource();
            }
            catch (System.Xml.XmlException exception)
            {
                throw new System.Xml.Xsl.XsltException(exception.Message, exception);
            }
            catch (System.Xml.Xsl.XsltException exception)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Emulates the behavior of Templates creating a XPathDocument instance.
        /// </summary>
        /// <param name="Source">The source with the Xsl.</param>
        /// <returns>A XPathDocument instance that could be used as Templates.</returns>
        public System.Xml.XPath.XPathDocument ToXPathDocument(BasicSource Source)
        {
            System.Xml.XPath.XPathDocument Template = null;
            if (Source is GenericSource)
            {
                GenericSource Generic = (GenericSource)Source;
                switch (Generic.Type)
                {
                    case GenericSource.TYPE.Uri:
                    case GenericSource.TYPE.File:
                        Template = new System.Xml.XPath.XPathDocument(Generic.Path);
                        break;
                    case GenericSource.TYPE.Stream:
                        Template = new System.Xml.XPath.XPathDocument(Generic.Stream);
                        break;
                    case GenericSource.TYPE.Reader:
                        Template = new System.Xml.XPath.XPathDocument(Generic.Reader);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                if (Source is DomSource)
                {
                    string temp_String = ((DomSource)Source).Node.OuterXml;
                    Template = new System.Xml.XPath.XPathDocument(new System.Xml.XmlTextReader(new System.IO.StringReader(temp_String)));
                }
                else
                {
                    if (Source is SaxSource)
                    {
                        XmlSource XmlSource = ((SaxSource)Source).Source;
                        if (XmlSource.Characters != null)
                            Template = new System.Xml.XPath.XPathDocument(XmlSource.Characters);
                        else
                        {
                            if (XmlSource.Bytes != null)
                                Template = new System.Xml.XPath.XPathDocument(XmlSource.Bytes);
                            else
                            {
                                if (XmlSource.Uri != null)
                                    Template = new System.Xml.XPath.XPathDocument(XmlSource.Uri);
                            }
                        }
                    }
                }
            }
            return Template;
        }

        /// <summary>
        /// Loads the StyleSheet that will be used for the transformations operations.
        /// </summary>
        /// <param name="StyleSheet">A GenericSourceSupport that contains the StyleSheet.</param>
        public void Load(BasicSource StyleSheet)
        {
            ((DefaultTransformerResolver)DefaultResolverFactory).Style = StyleSheet;
            if (StyleSheet is GenericSource)
            {
                GenericSource Generic = (GenericSource)StyleSheet;
                try
                {
                    switch (Generic.Type)
                    {
                        case GenericSource.TYPE.Uri:
                        case GenericSource.TYPE.File:
                            Transformer.Load(Generic.Path, DefaultResolverFactory);
                            break;
                        case GenericSource.TYPE.Stream:
                            Transformer.Load(new System.Xml.XmlTextReader(Generic.Stream), DefaultResolverFactory, this.GetType().Assembly.Evidence);
                            break;
                        case GenericSource.TYPE.Reader:
                            Transformer.Load(new System.Xml.XmlTextReader(Generic.Reader), DefaultResolverFactory, this.GetType().Assembly.Evidence);
                            break;
                        default:
                            break;
                    }
                    this.Stylesheet = StyleSheet;
                }
                catch (System.Xml.XmlException exception)
                {
                    if (this.ErrorListenerFactory == null)
                        throw new System.Xml.Xsl.XsltException(exception.Message, exception);
                    else
                        this.ErrorListenerFactory.FatalError(new System.Xml.Xsl.XsltException(exception.Message, exception));
                }
                catch (System.Xml.Xsl.XsltException exception)
                {
                    if (this.ErrorListenerFactory == null)
                        throw exception;
                    else
                        this.ErrorListenerFactory.FatalError(exception);
                }
            }
            else
            {
                if (StyleSheet is SaxSource)
                {
                    XmlSource Source = ((SaxSource)StyleSheet).Source;
                    try
                    {
                        if (Source.Characters != null)
                            Transformer.Load(new System.Xml.XmlTextReader(Source.Characters), DefaultResolverFactory, this.GetType().Assembly.Evidence);
                        else
                        {
                            if (Source.Bytes != null)
                                Transformer.Load(new System.Xml.XmlTextReader(Source.Bytes), DefaultResolverFactory, this.GetType().Assembly.Evidence);
                            else
                            {
                                if (Source.Uri != null)
                                {
                                    System.IO.FileStream tmp = new System.IO.FileStream(Source.Uri, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                                    Transformer.Load(new System.Xml.XmlTextReader(tmp), DefaultResolverFactory, this.GetType().Assembly.Evidence);
                                    tmp.Close();
                                }
                            }
                        }
                        this.Stylesheet = StyleSheet;
                    }
                    catch (System.Xml.XmlException exception)
                    {
                        if (this.ErrorListenerFactory == null)
                            throw new System.Xml.Xsl.XsltException(exception.Message, exception);
                        else
                            this.ErrorListenerFactory.FatalError(new System.Xml.Xsl.XsltException(exception.Message, exception));
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        if (this.ErrorListenerFactory == null)
                            throw exception;
                        else
                            this.ErrorListenerFactory.FatalError(exception);
                    }
                }
                else
                {
                    if (StyleSheet is DomSource)
                    {
                        try
                        {
                            string temp_String = ((DomSource)StyleSheet).Node.OuterXml;
                            Transformer.Load(new System.Xml.XmlTextReader(new System.IO.StringReader(temp_String)), DefaultResolverFactory, this.GetType().Assembly.Evidence);
                            this.Stylesheet = StyleSheet;
                        }
                        catch (System.Xml.XmlException exception)
                        {
                            if (this.ErrorListenerFactory == null)
                                throw new System.Xml.Xsl.XsltException(exception.Message, exception);
                            else
                                this.ErrorListenerFactory.FatalError(new System.Xml.Xsl.XsltException(exception.Message, exception));
                        }
                        catch (System.Xml.Xsl.XsltException exception)
                        {
                            if (this.ErrorListenerFactory == null)
                                throw exception;
                            else
                                this.ErrorListenerFactory.FatalError(exception);
                        }
                    }
                }
            }
        }


        /// <summary>
        /// Returns the value of a parameter in the parameters list.
        /// </summary>
        /// <param name="ParamName">The Name of the parameter.</param>
        /// <returns>An object that contains the value of the specified paramenter.</returns>
        public System.Object GetParameter(string ParamName)
        {
            if (Parameters != null)
                return Parameters.GetParam(ParamName, "");
            else
                return null;
        }

        /// <summary>
        /// Introduces a new parameter to the parameters list or modify the value of a parameter previously 
        /// introduced.
        /// </summary>
        /// <param name="ParamName">The name of the parameter.</param>
        /// <param name="ParamValue">An object instance with the parameter value.</param>
        public void SetParameter(string ParamName, System.Object ParamValue)
        {
            if (Parameters == null)
                Parameters = new System.Xml.Xsl.XsltArgumentList();
            Parameters.AddParam(ParamName, "", ParamValue);
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(BasicSource Source, BasicResult Result)
        {
            if (Source is GenericSource)
            {
                if (Result is GenericResult)
                    DoTransform((GenericSource)Source, (GenericResult)Result);
                else
                {
                    if (Result is DomResult)
                        DoTransform((GenericSource)Source, (DomResult)Result);
                    else
                        if (Result is SaxResult)
                            DoTransform((GenericSource)Source, (SaxResult)Result);
                }
            }
            else
            {
                if (Source is DomSource)
                {
                    if (Result is GenericResult)
                        DoTransform((DomSource)Source, (GenericResult)Result);
                    else
                    {
                        if (Result is DomResult)
                            DoTransform((DomSource)Source, (DomResult)Result);
                        else
                            if (Result is SaxResult)
                                DoTransform((DomSource)Source, (SaxResult)Result);
                    }
                }
                else
                {
                    if (Source is SaxSource)
                    {
                        if (Result is GenericResult)
                            DoTransform((SaxSource)Source, (GenericResult)Result);
                        else
                        {
                            if (Result is DomResult)
                                DoTransform((SaxSource)Source, (DomResult)Result);
                            else
                                if (Result is SaxResult)
                                    DoTransform((SaxSource)Source, (SaxResult)Result);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(GenericSource Source, GenericResult Result)
        {
            try
            {
                System.Xml.XmlDocument SourceDocument = new System.Xml.XmlDocument();
                switch (Source.Type)
                {
                    case GenericSource.TYPE.Uri:
                    case GenericSource.TYPE.File:
                        SourceDocument.Load(Source.Path);
                        break;
                    case GenericSource.TYPE.Stream:
                        SourceDocument.Load(Source.Stream);
                        break;
                    case GenericSource.TYPE.Reader:
                        SourceDocument.Load(Source.Reader);
                        break;
                    default:
                        SourceDocument = null;
                        ErrorListenerTransformer.Error(new System.Xml.Xsl.XsltException("The Xml Source can't be null", null));
                        break;
                }
                if (this.Stylesheet != null)
                {
                    try
                    {
                        switch (Result.Type)
                        {
                            case GenericResult.TYPE.Null:
                                break;
                            case GenericResult.TYPE.Stream:
                                Transformer.Transform(SourceDocument, Parameters, Result.Stream, DefaultResolverTransformer);
                                break;
                            case GenericResult.TYPE.File:
                            case GenericResult.TYPE.Uri:
                                System.IO.StreamWriter Temp_Writer = new System.IO.StreamWriter(Result.Id);
                                Transformer.Transform(SourceDocument, Parameters, Temp_Writer, DefaultResolverTransformer);
                                Temp_Writer.Close();
                                break;
                            case GenericResult.TYPE.Writer:
                                Transformer.Transform(SourceDocument, Parameters, Result.Writer, DefaultResolverTransformer);
                                Result.Writer.Close();
                                break;
                        }
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.FatalError(exception);
                    }
                }
                else
                    ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException("A Xsl stylesheet file must be defined before transform operation", null));
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }


        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(DomSource Source, GenericResult Result)
        {
            if (this.Stylesheet != null)
            {
                try
                {
                    switch (Result.Type)
                    {
                        case GenericResult.TYPE.Null:
                            break;
                        case GenericResult.TYPE.Stream:
                            Transformer.Transform(Source.Node, Parameters, Result.Stream, DefaultResolverTransformer);
                            break;
                        case GenericResult.TYPE.File:
                        case GenericResult.TYPE.Uri:
                            System.IO.StreamWriter Temp_Writer = new System.IO.StreamWriter(Result.Id);
                            Transformer.Transform(Source.Node, Parameters, Temp_Writer, DefaultResolverTransformer);
                            Temp_Writer.Close();
                            break;
                        case GenericResult.TYPE.Writer:
                            Transformer.Transform(Source.Node, Parameters, Result.Writer, DefaultResolverTransformer);
                            Result.Writer.Close();
                            break;
                    }
                }
                catch (System.Xml.Xsl.XsltException exception)
                {
                    ErrorListenerTransformer.FatalError(exception);
                }
                catch (System.Exception e)
                {
                    if (this.ErrorListenerTransformer == null)
                        throw new System.Xml.Xsl.XsltException(e.Message, e);
                    else
                        this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
                }
            }
            else
            {
                if (Source.Node is System.Xml.XmlDocument)
                {
                    switch (Result.Type)
                    {
                        case GenericResult.TYPE.Null:
                            break;
                        case GenericResult.TYPE.Stream:
                            ((System.Xml.XmlDocument)Source.Node).Save(Result.Stream);
                            Result.Stream.Close();
                            break;
                        case GenericResult.TYPE.File:
                        case GenericResult.TYPE.Uri:
                            ((System.Xml.XmlDocument)Source.Node).Save(Result.Id);
                            break;
                        case GenericResult.TYPE.Writer:
                            ((System.Xml.XmlDocument)Source.Node).Save(Result.Writer);
                            Result.Writer.Close();
                            break;
                    }
                }
                else
                {
                    switch (Result.Type)
                    {
                        case GenericResult.TYPE.Null:
                            break;
                        case GenericResult.TYPE.Stream:
                            System.IO.StreamWriter Writer = new System.IO.StreamWriter(Result.Stream);
                            Writer.Write(Source.Node.OuterXml);
                            Result.Stream.Close();
                            break;
                        case GenericResult.TYPE.File:
                        case GenericResult.TYPE.Uri:
                            System.IO.StreamWriter Temp_Writer = new System.IO.StreamWriter(Result.Id);
                            Temp_Writer.Write(Source.Node.OuterXml);
                            Temp_Writer.Close();
                            break;
                        case GenericResult.TYPE.Writer:
                            Result.Writer.Write(Source.Node.OuterXml);
                            Result.Writer.Close();
                            break;
                    }
                }
            }
        }


        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(DomSource Source, DomResult Result)
        {
            System.IO.MemoryStream tempStream = new System.IO.MemoryStream();
            try
            {
                if (this.Stylesheet != null)
                {
                    try
                    {
                        Transformer.Transform(Source.Node, Parameters, tempStream, DefaultResolverTransformer);
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.Error(exception);
                    }
                    tempStream.Position = 0;
                    System.Xml.XmlDocument TempDocument = (System.Xml.XmlDocument)Result.Node.OwnerDocument;
                    if (TempDocument == null)
                    {
                        TempDocument = (System.Xml.XmlDocument)Result.Node;
                    }
                    TempDocument.Load(tempStream);
                }
                else
                    ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException("A Xsl stylesheet file must be defined before transform operation", null));
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(GenericSource Source, DomResult Result)
        {
            try
            {
                System.Xml.XmlDocument SourceDocument = new System.Xml.XmlDocument();
                switch (Source.Type)
                {
                    case GenericSource.TYPE.Uri:
                    case GenericSource.TYPE.File:
                        SourceDocument.Load(Source.Path);
                        break;
                    case GenericSource.TYPE.Stream:
                        SourceDocument.Load(Source.Stream);
                        break;
                    case GenericSource.TYPE.Reader:
                        SourceDocument.Load(Source.Reader);
                        break;
                    default:
                        SourceDocument = null;
                        ErrorListenerTransformer.Error(new System.Xml.Xsl.XsltException("The Xml Source can't be null", null));
                        break;
                }
                System.IO.MemoryStream tempStream = new System.IO.MemoryStream();
                if (this.Stylesheet != null)
                {
                    try
                    {
                        Transformer.Transform(SourceDocument, Parameters, tempStream, DefaultResolverTransformer);
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.FatalError(exception);
                    }
                    tempStream.Position = 0;
                    System.Xml.XmlDocument TempDocument = (System.Xml.XmlDocument)Result.Node.OwnerDocument;
                    if (TempDocument == null)
                    {
                        TempDocument = (System.Xml.XmlDocument)Result.Node;
                    }
                    TempDocument.Load(tempStream);
                }
                else
                    ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException("A Xsl stylesheet file must be defined before transform operation", null));
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(SaxSource Source, SaxResult Result)
        {
            try
            {
                System.Xml.XmlDocument SourceDocument = new System.Xml.XmlDocument();
                System.IO.MemoryStream tempStream = new System.IO.MemoryStream();
                XmlSAXDocumentManager tempManager = new XmlSAXDocumentManager();
                tempManager.setContentHandler(Result.Handler);

                if (Result.LexHandler != null)
                    Source.Reader.setProperty("http://xml.org/sax/properties/lexical-handler", Result.LexHandler);

                if (Source.Source.Characters != null)
                    SourceDocument.Load(Source.Source.Characters);
                else
                {
                    if (Source.Source.Bytes != null)
                        SourceDocument.Load(Source.Source.Bytes);
                    else
                    {
                        if (Source.Source.Uri != null)
                            SourceDocument.Load(Source.Source.Uri);
                        else
                            return;
                    }
                }
                Transformer.Transform(SourceDocument, Parameters, tempStream, DefaultResolverTransformer);
                tempStream.Position = 0;
                tempManager.parse(tempStream);
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(SaxSource Source, DomResult Result)
        {
            try
            {
                System.IO.MemoryStream tempStream = new System.IO.MemoryStream();
                System.Xml.XmlDocument tempGSource = new System.Xml.XmlDocument();
                if (Source.Source.Characters != null)
                    tempGSource.Load(Source.Source.Characters.BaseStream);
                else
                {
                    if (Source.Source.Bytes != null)
                        tempGSource.Load(Source.Source.Bytes);
                    else
                    {
                        if (Source.Source.Uri != null)
                            tempGSource.Load(Source.Source.Uri);
                        else
                            return;
                    }
                }
                if (this.Stylesheet != null)
                {
                    try
                    {
                        Transformer.Transform(tempGSource, Parameters, tempStream, DefaultResolverTransformer);
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.FatalError(exception);
                    }
                    tempStream.Position = 0;
                    System.Xml.XmlDocument TempDocument = (System.Xml.XmlDocument)Result.Node.OwnerDocument;
                    if (TempDocument == null)
                    {
                        TempDocument = (System.Xml.XmlDocument)Result.Node;
                    }
                    TempDocument.Load(tempStream);
                }
                else
                    ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException("A Xsl stylesheet file must be defined before transform operation", null));
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(SaxSource Source, GenericResult Result)
        {
            try
            {
                System.Xml.XmlDocument tempGSource = new System.Xml.XmlDocument();
                if (Source.Source.Characters != null)
                    tempGSource.Load(Source.Source.Characters.BaseStream);
                else
                {
                    if (Source.Source.Bytes != null)
                        tempGSource.Load(Source.Source.Bytes);
                    else
                    {
                        if (Source.Source.Uri != null)
                            tempGSource.Load(Source.Source.Uri);
                        else
                            return;
                    }
                }
                if (this.Stylesheet != null)
                {
                    try
                    {
                        switch (Result.Type)
                        {
                            case GenericResult.TYPE.Null:
                                break;
                            case GenericResult.TYPE.Stream:
                                Transformer.Transform(tempGSource, Parameters, Result.Stream, DefaultResolverTransformer);
                                break;
                            case GenericResult.TYPE.File:
                            case GenericResult.TYPE.Uri:
                                System.IO.StreamWriter Temp_Writer = new System.IO.StreamWriter(Result.Id);
                                Transformer.Transform(tempGSource, Parameters, Temp_Writer, DefaultResolverTransformer);
                                Temp_Writer.Close();
                                break;
                            case GenericResult.TYPE.Writer:
                                Transformer.Transform(tempGSource, Parameters, Result.Writer, DefaultResolverTransformer);
                                Result.Writer.Close();
                                break;
                        }
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.FatalError(exception);
                    }
                }
                else
                    ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException("A Xsl stylesheet file must be defined before transform operation", null));
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }

        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(GenericSource Source, SaxResult Result)
        {
            try
            {
                XmlSAXDocumentManager tempManager = new XmlSAXDocumentManager();
                tempManager.setContentHandler(Result.Handler);
                if (Result.LexHandler != null)
                    tempManager.setProperty("http://xml.org/sax/properties/lexical-handler", Result.LexHandler);
                if (this.Stylesheet != null)
                {
                    System.IO.MemoryStream tempStream = new System.IO.MemoryStream();
                    System.Xml.XmlDocument SourceDocument = new System.Xml.XmlDocument();
                    switch (Source.Type)
                    {
                        case GenericSource.TYPE.Uri:
                        case GenericSource.TYPE.File:
                            SourceDocument.Load(Source.Path);
                            break;
                        case GenericSource.TYPE.Stream:
                            SourceDocument.Load(Source.Stream);
                            break;
                        case GenericSource.TYPE.Reader:
                            SourceDocument.Load(Source.Reader);
                            break;
                        default:
                            SourceDocument = null;
                            ErrorListenerTransformer.Error(new System.Xml.Xsl.XsltException("The Xml Source can't be null", null));
                            break;
                    }
                    try
                    {
                        Transformer.Transform(SourceDocument, Parameters, tempStream, DefaultResolverTransformer);
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.FatalError(exception);
                    }
                    tempStream.Position = 0;
                    tempManager.parse(tempStream);

                }
                else
                {
                    if (Source.Reader != null)
                        tempManager.parse(Source.Reader.BaseStream);
                    else
                    {
                        if (Source.Stream != null)
                            tempManager.parse(Source.Stream);
                        else
                        {
                            if (Source.Path != null)
                                tempManager.parse(Source.Path);
                            else
                                return;
                        }
                    }
                }
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }


        /// <summary>
        /// Makes the tranformation from the specified source, to the specified target.
        /// </summary>
        /// <param name="Source">The XML source to be transformed.</param>
        /// <param name="Result">The result of the transformation.</param>
        public void DoTransform(DomSource Source, SaxResult Result)
        {
            try
            {
                System.IO.MemoryStream tempStream;
                if (this.Stylesheet != null)
                {
                    tempStream = new System.IO.MemoryStream();
                    try
                    {
                        Transformer.Transform(Source.Node, Parameters, tempStream, DefaultResolverTransformer);
                    }
                    catch (System.Xml.Xsl.XsltException exception)
                    {
                        ErrorListenerTransformer.FatalError(exception);
                    }
                    tempStream.Position = 0;
                }
                else
                {
                    char[] c = Source.Node.OuterXml.ToCharArray();
                    byte[] x = new byte[c.Length];
                    for (int i = 0; i < c.Length; i++)
                        x[i] = System.Convert.ToByte(c[i]);
                    tempStream = new System.IO.MemoryStream(x);
                }
                XmlSAXDocumentManager tempManager = new XmlSAXDocumentManager();
                tempManager.setContentHandler(Result.Handler);
                if (Result.LexHandler != null)
                    tempManager.setProperty("http://xml.org/sax/properties/lexical-handler", Result.LexHandler);
                tempManager.parse(tempStream);
            }
            catch (System.Exception e)
            {
                if (this.ErrorListenerTransformer == null)
                    throw new System.Xml.Xsl.XsltException(e.Message, e);
                else
                    this.ErrorListenerTransformer.FatalError(new System.Xml.Xsl.XsltException(e.Message, e));
            }
        }

        /// <summary>
        /// This method indicates if a feature is supported by the current instance.
        /// </summary>
        /// <param name="feature">A string asociated to a feature.</param>
        /// <returns>True if the feature is supported otherwise false.</returns>
        public bool IsSupported(string feature)
        {
            bool result;
            switch (feature)
            {
                case "GENERICSOURCE":
                case "GENERICRESULT":
                case "DOMSOURCE":
                case "DOMRESULT":
                case "SAXSOURCE":
                case "SAXRESULT":
                case "TRANSFORMERHANDLER":
                case "XMLFILTERSUPPORT":
                    result = true;
                    break;
                default:
                    result = false;
                    break;
            }
            return result;
        }

        /// <summary>
        /// Represent the Default error handling for transform operations
        /// </summary>
        public class DefaultXsltExceptionManager : XsltExceptionManager
        {
            public System.IO.StreamWriter StandardError = null;

            /// <summary>
            /// Default constructor for the class.
            /// </summary>
            public DefaultXsltExceptionManager()
            {
                StandardError = new System.IO.StreamWriter(System.Console.OpenStandardError());
            }

            /// <summary>
            /// Manages when an exception was thrown in the Transform operation of the TranformerSupport class.
            /// </summary>
            /// <param name="exception">The exception thrown by the TransformerSupport instance.</param>
            public void Error(System.Xml.Xsl.XsltException exception)
            {
                StandardError.WriteLine(exception);
            }

            /// <summary>
            /// Manages when an exception was thrown in the Transform operation of the TranformerSupport class.
            /// </summary>
            /// <param name="exception">The exception thrown by the TransformerSupport instance.</param>
            public void FatalError(System.Xml.Xsl.XsltException exception)
            {
                StandardError.WriteLine(exception);
                throw exception;
            }

            /// <summary>
            /// Manages when an exception was thrown in the Transform operation of the TranformerSupport class.
            /// </summary>
            /// <param name="exception">The exception thrown by the TransformerSupport instance.</param>
            public void Warning(System.Xml.Xsl.XsltException exception)
            {
                StandardError.WriteLine(exception);
            }
        }
    }
}
